#pragma once

#include "Ary.h"

VOID_NS1(nVoid)

class tStr : public string
{
public:

	typedef string tBase; 
	
	//------------------------- 静态接口

	/// 空白字符？
	static bool scIsWhiteSpace(char a_Cha)
	{
		switch (a_Cha)
		{
		case ' ':
		case '\t':
		case '\v':
		case '\f':
		case '\r':
		case '\n':
			return true;
		}
		return false;
	}

	/// 一字节的16进制表示
	static tStr scHexOf(unsigned char a_Val, bool a_Upper = false)
	{
		int o_16 = a_Val / 16, o_1 = a_Val % 16;
		char o_B = a_Upper ? 'A' : 'a';
		tStr o_Rst;
		if (o_16 < 10) { o_Rst += o_16; }
		else { o_Rst += (char)(o_B + (o_16 - 10)); }
		if (o_1 < 10) { o_Rst += o_1; }
		else { o_Rst += (char)(o_B + (o_1 - 10)); }
		return o_Rst;
	}

	/// 两字节的16进制表示
	static tStr scHexOf(unsigned short a_Val, bool a_Upper = false)
	{
		tStr o_Rst;
		o_Rst += scHexOf((unsigned char)(a_Val >> 8), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val), a_Upper);
		return o_Rst;
	}

	/// 四字节的16进制表示
	static tStr scHexOf(unsigned int a_Val, bool a_Upper = false)
	{
		tStr o_Rst;
		o_Rst += scHexOf((unsigned char)(a_Val >> 24), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val >> 16), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val >> 8), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val), a_Upper);
		return o_Rst;
	}

	/// 八字节的16进制表示
	static tStr scHexOf(unsigned long long a_Val, bool a_Upper = false)
	{
		tStr o_Rst;
		o_Rst += scHexOf((unsigned char)(a_Val >> 56), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val >> 48), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val >> 40), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val >> 32), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val >> 24), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val >> 16), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val >> 8), a_Upper);
		o_Rst += scHexOf((unsigned char)(a_Val), a_Upper);
		return o_Rst;
	}

	/// 十六进制转整数
	static unsigned long long scHexTo(tStr a_Hex)
	{
		unsigned long long o_Rst = 0;
		int o_Len = a_Hex.cLen(), i = o_Len - 1, o_Base = 1;
		while (i >= 0)
		{
			char o_Cha = a_Hex[i];
			if ('0' <= o_Cha && o_Cha <= '9') { o_Rst += unsigned long long((int)o_Cha - (int)'0') * o_Base; }
			else if (o_Cha >= 'a') { o_Rst += (unsigned long long((int)o_Cha - (int)'a') + 10) * o_Base; }
			else if (o_Cha >= 'A') { o_Rst += (unsigned long long((int)o_Cha - (int)'A') + 10) * o_Base; }
			--i;
			o_Base *= 16;
		}
		return o_Rst;
	}

	//------------------------- 接口

	tStr(char const* a_pCStr = "")
	{
		if (a_pCStr && ('\0' != a_pCStr[0]))
		{
			this->assign(a_pCStr);
		}
	}

	tStr(char* a_pCStr)
	{
		if (a_pCStr && ('\0' != a_pCStr[0]))
		{
			this->assign(a_pCStr);
		}
	}

	tStr(char a_Char)
	{
		this->push_back(a_Char);
	}

	tStr(tStr const& a_RHS)
		: string(a_RHS)
	{ }

	explicit tStr(string const& a_Str)
		: string(a_Str)
	{ }

	explicit tStr(bool a_Val)
		: string(a_Val ? "true" : "false")
	{ }

	explicit tStr(int a_Val)
		: string(to_string(a_Val))
	{ }

	explicit tStr(unsigned int a_Val)
		: string(to_string(a_Val))
	{ }

	explicit tStr(long a_Val)
		: string(to_string(a_Val))
	{ }

	explicit tStr(unsigned long a_Val)
		: string(to_string(a_Val))
	{ }

	explicit tStr(long long a_Val)
		: string(to_string(a_Val))
	{ }

	explicit tStr(unsigned long long a_Val)
		: string(to_string(a_Val))
	{ }

	explicit tStr(float a_Val)
		: string(to_string(a_Val))
	{ }

	explicit tStr(double a_Val)
		: string(to_string(a_Val))
	{ }

	explicit tStr(long double a_Val)
		: string(to_string(a_Val))
	{ }

	//template<class a_tVal>
	//explicit tStr(a_tVal const& a_Val)
	//{
	//	this->assign((tStr)a_Val);//
	//}

	tStr& operator =(tStr const& a_RHS)
	{
		this->assign(a_RHS);
		return *this;
	}

	tStr& operator =(char a_RHS)
	{
		this->resize(1);
		(*this)[0] = a_RHS;
		return *this;
	}

	tStr& operator =(char const* a_RHS)
	{
		if (a_RHS && ('\0' != a_RHS[0]))
		{
			this->assign(a_RHS);
		}
		else
		{
			this->clear();
		}
		return *this;
	}

	template<class a_tRHS>
	tStr& operator =(a_tRHS const& a_RHS)
	{
		this->assign(tStr(a_RHS));
		return *this;
	}

	operator bool() const
	{
		return this->length() > 0;
	}

	operator char() const
	{
		return (this->length() > 0) ? (*this)[0] : '\0';
	}

	operator char const* () const
	{
		return this->c_str();
	}

	template<class a_tVal>
	tStr& operator +=(a_tVal const& a_Val)
	{
		this->tBase::operator +=(tStr(a_Val));
		return *this;
	}

	friend tStr operator +(tStr const& a_S1, tStr const& a_S2)
	{
		tStr o_Temp(a_S1);
		o_Temp += tStr(a_S2);
		return o_Temp;
	}

	template<class a_tVal>
	friend tStr operator +(tStr const& a_S1, a_tVal const& a_S2)
	{
		return a_S1 + tStr(a_S2);
	}

	template<class a_tVal>
	friend tStr operator +(a_tVal const& a_S1, tStr const& a_S2)
	{
		return tStr(a_S1) + a_S2;
	}

	int cLen() const
	{
		return (int)this->length();
	}

	int cFind(tStr const& a_Sub, int a_Off = 0) const
	{
		return (int)this->find(a_Sub, a_Off);
	}

	int cFind(char a_Cha, int a_Off = 0) const
	{
		return (int)this->find(a_Cha, a_Off);
	}

	bool cHasPrefix(tStr const& a_Sub) const
	{
		return (this->cLen() >= a_Sub.cLen()) && (this->cSlice(0, a_Sub.cLen()) == a_Sub);
	}

	bool cHasSuffix(tStr const& a_Sub) const
	{
		return (this->cLen() >= a_Sub.cLen()) && (this->cSlice(this->cLen() - a_Sub.cLen()) == a_Sub);
	}

	int cCharCodeAt(int a_Idx) const
	{
		return (int)(unsigned char)(*this)[a_Idx];
	}

	/// 修剪
	/// a_Mode: 0=左，1=右，2=左右
	tStr cTrim(int a_Mode = 2) const
	{
		tStr o_Rst(*this);
		if ((a_Mode == 0) || (a_Mode == 2))
		{
			int o_Len = o_Rst.cLen(), o_Idx;
			for (o_Idx = 0; o_Idx < o_Len; ++o_Idx)
			{
				if (!scIsWhiteSpace(o_Rst[o_Idx]))
				{ break; }
			}
			if (o_Idx >= o_Len) { return tStr(); }
			o_Rst = o_Rst.cSlice(o_Idx);
		}

		if ((a_Mode == 1) || (a_Mode == 2))
		{
			int o_Idx;
			for (o_Idx = o_Rst.cLen() - 1; o_Idx >= 0; --o_Idx)
			{
				if (!scIsWhiteSpace(o_Rst[o_Idx]))
				{ break; }
			}
			if (o_Idx < 0) { return tStr(); }
			o_Rst = o_Rst.cSlice(0, o_Idx + 1);
		}
		return o_Rst;
	}

	/// 小写
	tStr cLower() const
	{
		tStr o_Rst(*this);
		transform(this->begin(), this->end(), o_Rst.begin(), ::tolower);
		return o_Rst;
	}

	/// 大写
	tStr cUpper() const
	{
		tStr o_Rst(*this);
		transform(this->begin(), this->end(), o_Rst.begin(), ::toupper);
		return o_Rst;
	}

	/// 子串
	tStr cSlice(int a_Start = 0, int a_Stop = -1) const
	{
		if (a_Start < 0) { a_Start = 0; }
		else if (a_Start >= (int)this->length()) { return tStr(); }
		if (a_Stop < 0 || a_Stop >= (int)this->length()) { a_Stop = (int)this->length(); }
		if (a_Start >= a_Stop) { return tStr(); }
		return tStr(this->substr(a_Start, (size_t)(a_Stop - a_Start)));
	}

	/// 替换子串
	tStr cReplace(tStr a_From, tStr a_To) const
	{
		tStr o_Rst(*this);
		tStr o_To(a_To);
		size_t o_ToLen = o_To.length();
		size_t o_Idx = 0;
		while ((o_Idx = this->find((char const*)a_From, o_Idx)) != tStr::npos)
		{
			o_Rst = o_Rst.replace(o_Idx, o_ToLen, o_To);
			o_Idx += o_ToLen;
		}
		return o_Rst;
	}

	/// 转义
	tStr cEscape() const
	{
		return this->cReplace("\\", "\\\\").cReplace("\"", "\\\"").cReplace("\t", "\\t").cReplace("\v", "\\v").cReplace("\f", "\\f").cReplace("\r", "\\r").cReplace("\n", "\\n");
	}

	/// 解除转义
	tStr cUnescape() const
	{
		return this->cReplace("\\n", "\n").cReplace("\\r", "\r").cReplace("\\f", "\f").cReplace("\\v", "\v").cReplace("\\t", "\t").cReplace("\\\"", "\"").cReplace("\\\\", "\\");
	}

	/// 编码Unicode转义“\u????”，其中“?”是 0-9A-Fa-f
	///【警告：本函数只处理上述形式，忽略其他转义】
	tStr cEncodeUnicodeEscape() const
	{
		tStr o_Rst;
		int o_Len = this->cLen();
		for (int i = 0; i < o_Len; ++i)
		{
			unsigned char o_Code = (unsigned char)((*this)[i]);
			if (o_Code < 32)
			{
				o_Rst += "\\u00";
				o_Rst += tStr::scHexOf(o_Code);
			}
			else if (o_Code > 127)
			{
				o_Rst += "\\u";	
				if (i + 1 < o_Len)
				{
					o_Rst += tStr::scHexOf(o_Code);
					o_Rst += tStr::scHexOf((unsigned char)((*this)[(size_t)i + 1]));
					++i;
				}
				else
				{
					o_Rst += "00";
					o_Rst += tStr::scHexOf(o_Code);
				}
			}
			else
			{
				o_Rst += (*this)[i];
			}
		}
		return o_Rst;
	}

	/// 解码Unicode转义“\u????”，其中“?”是 0-9A-Fa-f 
	///【警告：本函数只处理上述形式，忽略其他转义】
	tStr cDecodeUnicodeEscape() const
	{
		tStr o_Rst;
		int o_Len = this->cLen(), i = 0;
		if (o_Len < 6) { return *this; }
		while (i <= o_Len - 6)
		{
			if ((*this)[i] == '\\' && (((*this)[(size_t)i + 1] == 'U') || ((*this)[(size_t)i + 1] == 'u')))
			{
				unsigned short o_B2 = (unsigned short)scHexTo(this->cSlice(i + 2, i + 6));
				o_Rst += (char)(o_B2 >> 8);
				o_Rst += (char)(o_B2);
				i += 6;
			}
			else
			{
				o_Rst += (*this)[i];
				++i;
			}
		}
		o_Rst += this->cSlice(i);
		return o_Rst;
	}

	/// 重复，a_Cnt≤0时返回空串
	tStr cRepeat(int a_Cnt) const
	{
		tStr o_Rst;
		while (a_Cnt-- > 0) { o_Rst += *this; }
		return o_Rst;
	}

	/// 拆分字符串
	tAry<tStr> cSplit(tStr a_Sep) const
	{
		tAry<tStr> o_Rst;
		int o_SL = (int)a_Sep.length(), o_L = (int)this->length(), o_B = 0;
		while (true)
		{
			int o_E = (int)this->find(a_Sep, o_B);
			if (o_E < 0)
			{ 
				o_Rst.push_back(this->cSlice(o_B, o_L));
				break; 
			}
			o_Rst.push_back(this->cSlice(o_B, o_E));
			o_B = o_E + o_SL;
			if (o_B >= o_L)
			{
				o_Rst.push_back(tStr());
				break;
			}
		}
		return o_Rst;
	}

	//======================================================== 静态接口

	/// 拼字符串
	static tStr scCat()
	{
		return tStr();
	}

	template<class a_tArg, class... a_tArgs>
	static tStr scCat(a_tArg a_Arg, a_tArgs... a_Args)
	{
		return scCatSep("", a_Arg, a_Args...);
	}

	template<class a_tSep>
	static tStr scCatSep(a_tSep a_Sep)
	{
		return tStr();
	}

	template<class a_tSep, class a_tArg, class... a_tArgs>
	static tStr scCatSep(a_tSep a_Sep, a_tArg a_Arg, a_tArgs... a_Args)
	{
		tStr o_Rst;
		seCatSep(o_Rst, tStr(a_Sep), a_Arg, a_Args...); // 返回值作为参赛提供，可以避免内存碎片
		return o_Rst;
	}

	template<class a_tArg, class... a_tArgs>
	static void seCatSep(tStr& a_Buf, tStr a_Sep, a_tArg a_Arg, a_tArgs... a_Args) // 递归的一般形式
	{
		a_Buf += tStr(a_Arg);
		a_Buf += a_Sep;
		seCatSep(a_Buf, a_Sep, a_Args...);
	}

	static void seCatSep(tStr& a_Buf, tStr a_Sep) // 递归的结束形式
	{
		if (a_Sep.length() > 0)
		{
			a_Buf.resize(a_Buf.length() - a_Sep.length());
		}
	}

	/// 连结字符串
	template<class a_tCont>
	static tStr scJoin(tStr a_Sep, a_tCont const& a_Cont)
	{
		tStr o_Rst;
		int i = 0;
		for (auto o_Item: a_Cont)
		{
			if (i > 0)
			{
				o_Rst += a_Sep;
			}
			o_Rst += tStr(o_Item);
			++i;
		}
		return o_Rst;
	}

	/// 缩进
	static tStr scIndent(int a_Cnt, char a_Cha = ' ')
	{
		tStr o_Rst;
		while (a_Cnt-- > 0)
		{
			o_Rst += a_Cha;
		}
		return o_Rst;
	}

};


VOID_NS0(nVoid)